﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Legend.Component.Common;
using Legend.Component.Interface;
using Microsoft.Xna.Framework.Content;
using Legend.Object;

namespace Legend.Component.Common
{
    public class StateManager : IStateManager
    {
        class InternalState
        {
            public IState State;
            public int BootTime;
            public Type StateType;
            public int LastPulse;
        }

        private GameObject owner;
        private List<InternalState> stateList = new List<InternalState>();
        private List<InternalState> removedList = new List<InternalState>();

        public GameObject Owner
        {
            get { return owner; }
            set { owner = value; }
        }

        public Type UniqueType
        {
            get { return typeof(IStateManager); }
        }

        public void AddState<T>(T state) where T : IState
        {
            InternalState internalState = new InternalState();
            internalState.BootTime = state.ActivationTime;
            internalState.State = state;
            internalState.StateType = typeof(T);
            internalState.LastPulse = 0;

            stateList.Add(internalState);
        }

        public void Update(GameTime gameTime, ContentManager contentManager)
        {
            foreach (InternalState state in stateList)
            {
                if (state.BootTime >= 0 &&
                    state.BootTime < (int)gameTime.ElapsedGameTime.TotalMilliseconds)
                {
                    state.State.OnActivated();
                    state.LastPulse = state.State.Duration / state.State.Pulse;
                }
                
                state.BootTime -= (int)gameTime.ElapsedGameTime.TotalMilliseconds;
                int remainTime = state.BootTime + state.State.Duration;

                if (remainTime < 0)
                {
                    state.State.OnDeactivated();
                    removedList.Add(state);
                }
                else if (state.LastPulse != remainTime / state.State.Pulse)
                {
                    state.LastPulse = remainTime / state.State.Pulse;
                    state.State.OnPulse(state.State.Duration - remainTime);
                }
            }

            foreach (InternalState state in removedList)
            {
                stateList.Remove(state);
            }
        }

        public void Clear()
        {
            foreach (InternalState state in stateList)
            {
                state.State.OnDeactivated();
            }
            stateList.Clear();
        }

        public bool FindState<T>()
        {
            foreach (InternalState state in stateList)
            {
                if (state.StateType == typeof(T))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
